﻿using YNTK.Common.Core.Manager;
using YNTK.Common.Enum;
using YNTK.Common.Extension;
using YNTK.Common.Filter;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.FriendlyException;
using YNTK.WorkFlow.Entitys;
using YNTK.WorkFlow.Entitys.Enum;
using YNTK.WorkFlow.Interfaces.FlowEngine;
using YNTK.WorkFlow.Interfaces.FlowTask;
using YNTK.WorkFlow.Interfaces.FlowTask.Repository;
using YNTK.SubDev.Interfaces.ZyOaWfSeal;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YNTK.SubDev.Entitys;
using YNTK.SubDev.Entitys.Dto.ZyOaWfSeal;
using Yitter.IdGenerator;
using YNTK.Common.Helper;
using YNTK.JsonSerialization;
using YNTK.System.Interfaces.System;

namespace YNTK.SubDev.ZyOaWfSeal
{
    /// <summary>
    /// 用章申请服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "SubDev",Name = "ZyOaWfSeal", Order = 200)]
    [Route("api/SubDev/[controller]")]
    public class ZyOaWfSealService : IZyOaWfSealService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<ZyOaWfSealEntity> _zyOaWfSealRepository;
        private readonly IBillRullService _billRuleService;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;
        private readonly IFlowTaskService _flowTaskService;
        private readonly IFlowTaskRepository _flowTaskRepository;
        private readonly IFlowEngineService _flowEngineService;

        /// <summary>
        /// 初始化一个<see cref="ZyOaWfSealService"/>类型的新实例
        /// </summary>
        public ZyOaWfSealService(
            ISqlSugarRepository<ZyOaWfSealEntity> zyOaWfSealRepository,
            IBillRullService billRuleService,
            IUserManager userManager, 
            IFlowTaskService flowTaskService, 
            IFlowTaskRepository flowTaskRepository, 
            IFlowEngineService flowEngineService)
        {
            _zyOaWfSealRepository = zyOaWfSealRepository;            
            _db = _zyOaWfSealRepository.Context;
            _billRuleService = billRuleService;
            _userManager = userManager;
            _flowTaskService = flowTaskService;
            _flowTaskRepository = flowTaskRepository;
            _flowEngineService = flowEngineService;
        }

        /// <summary>
        /// 获取用章申请
        /// </summary>
        /// <param name="id">参数</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<ZyOaWfSealEntity>().FirstAsync(p => p.Id == id);
            var output = entity.Adapt<ZyOaWfSealInfoOutput>();
            return output;
        }

        /// <summary>
		/// 获取用章申请列表
		/// </summary>
		/// <param name="input">请求参数</param>
		/// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] ZyOaWfSealListQueryInput input)
        {
            var sidx = input.sidx == null ? "creatorTime" : input.sidx;
            var data = await _db.Queryable<ZyOaWfSealEntity,FlowTaskEntity>((a,b) => new JoinQueryInfos(JoinType.Left, a.Id == b.Id))
                .WhereIF(!string.IsNullOrEmpty(input.sealName), a => a.SealName.Contains(input.sealName))
                .WhereIF(!string.IsNullOrEmpty(input.sealType), a => a.SealType.Contains(input.sealType))
                .WhereIF(!string.IsNullOrEmpty(input.creatorUserId), a => a.CreatorUserId.Equals(input.creatorUserId))
                .Select((a,b)=> new 
                {
                    id = a.Id,
                    sealName = a.SealName,
                    enCode = a.EnCode,
                    sealCount = a.SealCount,
                    sealType = a.SealType,
                    sealDate = a.SealDate,
                    creatorUserId = a.CreatorUserId,
                    creatorTime = a.CreatorTime,
                    flowState = b.Status,
                    flowId = b.FlowId
                }).MergeTable().Select<ZyOaWfSealListOutput>().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
                return TkPageResult<ZyOaWfSealListOutput>.SqlSugarPageResult(data);
        }

        /// <summary>
        /// 新建用章申请
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] ZyOaWfSealCrInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            var entity = input.Adapt<ZyOaWfSealEntity>();
            entity.Id = YitIdHelper.NextId().ToString();
            entity.EnCode = await _billRuleService.GetBillNumber("ZYYZ_WF");
            entity.CreatorUserId = _userManager.UserId;
            entity.CreatorTime = DateTime.Now;  
            var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
            _ = newEntity ?? throw YNTKException.Oh(ErrorCode.COM1000);
            if (input.flowState == 0)
            {
                var flowEngineEntity = await _flowEngineService.GetInfoByEnCode("#visualDevZyOaWfSeal");
                await FlowSubmit(newEntity.Id, flowEngineEntity);
            }
        }

        /// <summary>
        /// 更新用章申请
        /// </summary>
        /// <param name="id">主键</param>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task Update(string id, [FromBody] ZyOaWfSealUpInput input)
        {
            var entity = input.Adapt<ZyOaWfSealEntity>();
            var isOk = await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
            if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.COM1001);
            if (input.flowState.Equals(0))
            {
                var flowEngineEntity = await _flowEngineService.GetInfoByEnCode("#visualDevZyOaWfSeal");
                await FlowSubmit(entity.Id, flowEngineEntity);
            }
        }

        /// <summary>
        /// 删除用章申请
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var entity = await _db.Queryable<ZyOaWfSealEntity>().FirstAsync(p => p.Id == id);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.COM1005);
            var isOk = await _db.Deleteable<ZyOaWfSealEntity>().Where(d => d.Id == id).ExecuteCommandAsync();
            if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.COM1002);
        }
        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowEngineEntity">流程信息</param>
        /// <returns></returns>
        private async Task FlowSubmit(string id, FlowEngineEntity flowEngineEntity)
        {
            var zyOaWfSealEntity = await _zyOaWfSealRepository.FirstOrDefaultAsync(x => x.Id == id);
            try
            {
                DbScoped.SugarScope.BeginTran();

                #region 业务信息
                
                await _zyOaWfSealRepository.UpdateAsync(zyOaWfSealEntity);

                #endregion

                #region 流程信息
                var flowTaskEntity = await _flowTaskRepository.GetTaskInfo(id);
                if (flowTaskEntity.IsNullOrEmpty())
                {
                    await _flowTaskService.Submit("", flowEngineEntity.Id, id, _userManager.User.RealName + "的" + flowEngineEntity.FullName, 1, null, zyOaWfSealEntity.Adapt<ZyOaWfSealCrInput>(), 0);
                }
                else
                {
                    await _flowTaskService.Submit(id, flowEngineEntity.Id, id, _userManager.User.RealName + "的"  + flowEngineEntity.FullName, 1, null, zyOaWfSealEntity.Adapt<ZyOaWfSealCrInput>(), 0);
                }
                #endregion

                DbScoped.SugarScope.CommitTran();
            }
            catch (Exception)
            {
                DbScoped.Sugar.RollbackTran();
                throw;
            }
        }

        /// <summary>
        /// 撤回审核
        /// </summary>
        /// <param name="flowTaskEntity">流程任务</param>
        /// <param name="flowHandleModel">流程经办</param>
        private async Task FlowRevoke(FlowTaskEntity flowTaskEntity, string flowHandleModel)
        {
            var zyOaWfSealEntity = await _zyOaWfSealRepository.FirstOrDefaultAsync(x => x.Id == flowTaskEntity.ProcessId);
            try
            {
                DbScoped.SugarScope.BeginTran();

                #region 业务信息
                await _zyOaWfSealRepository.UpdateAsync(zyOaWfSealEntity);
                #endregion

                #region 流程信息
                var flowTaskNodeEntityList = await _flowTaskRepository.GetTaskNodeList(flowTaskEntity.Id);
                var flowTaskNodeEntity = flowTaskNodeEntityList.Find(m => m.SortCode == 2);
                if (flowTaskNodeEntity.Completion > 0)
                {
                    throw new Exception("当前流程被处理，无法撤回流程");
                }
                else
                {
                    await _flowTaskService.Revoke(flowTaskEntity, flowHandleModel);
                }
                #endregion

                DbScoped.SugarScope.CommitTran();
            }
            catch (Exception)
            {
                DbScoped.Sugar.RollbackTran();
                throw;
            }
        }
    }
}